package com.mxpio.erp.inventory.service.impl;

import com.mxpio.erp.common.enums.*;
import com.mxpio.erp.common.inventory.entity.*;
import com.mxpio.erp.common.inventory.service.*;
import com.mxpio.erp.common.technology.entity.Item;
import com.mxpioframework.common.exception.MBootException;
import com.mxpioframework.common.util.SpringUtil;
import com.mxpioframework.common.vo.Result;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.jpa.query.*;
import com.mxpioframework.system.service.SnRuleService;
import com.mxpioframework.system.service.impl.BaseServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author : 吴盼盼
 * @Datetime : 2022/10/6 21:21
 * @Desc :
 * @Modor :  Modifytime:
 * @modDesc :
 */
@Service
public class InventoryServiceImpl extends BaseServiceImpl<Inventory> implements InventoryService {
    @Autowired
    private InventoryItemService inventoryItemService;
    @Autowired
    private VInvLotStockService vInvLotStockService;

    @Autowired
    private InventoryReviewService inventoryReviewService;
    @Override
    @Transactional
    public Result<Inventory> saveInventory(Inventory inventory) {
        String inventoryCode = inventory.getInventoryCode();
        Inventory dbInventory = getById(Inventory.class, inventoryCode);
        if (!StringUtils.equals(dbInventory.getInventoryWay(),inventory.getInventoryWay())){//盘点方法 是否发生变化
            String inventoryWay = inventory.getInventoryWay();
            List<InventoryItem> dbInventoryItemList = JpaUtil.linq(InventoryItem.class).equal("inventoryCode", inventoryCode).list();
            if (StringUtils.equals(inventoryWay,InventoryEnums.InventoryWay.BLIND.getCode())){//更新为盲盘
                for (InventoryItem item:dbInventoryItemList){
                    item.setQuantityStr("*");
                }
            }else{//更新为明盘
                for (InventoryItem item:dbInventoryItemList){
                    item.setQuantityStr(item.getQuantity().toPlainString());
                }
            }
            JpaUtil.update(dbInventoryItemList);//更新 盘点展示数量 值
        }
        save(inventory);//保存主单
        return Result.OK(inventory);
    }


    @Override
    @Transactional
    public Result<Inventory> review(String inventoryCode, InventoryReview inventoryReview) {
        Inventory inventory = this.getById(Inventory.class, inventoryCode);
        if (!StringUtils.equals(inventory.getInventoryStatus(),InventoryEnums.InventoryStatus.REVIEW.getStatusCode())){
            return Result.error("仅待复核状态的数据可以执行复核操作");
        }
        List<InventoryItem> inventoryItemList = JpaUtil.linq(InventoryItem.class).equal("inventoryCode", inventory.getInventoryCode()).list();
        if (!inventoryItemList.isEmpty()){
            for (InventoryItem item:inventoryItemList){
                //校验盘点明细是否填写责任单位
                if (item.getHandleMethod()!=null //部分盘点时，有为空的情况
                        &&!InventoryEnums.HandleMethod.EQUAL.getCode().equals(item.getHandleMethod())
                        &&StringUtils.isBlank(item.getResponsibleUnit())){
                    return Result.error("未维护责任单位，请维护后再提交复核！");
                }
            }
        }
        if (StringUtils.equals(inventoryReview.getReviewOpinion(), AuditEnums.Purc.OK.getTypeCode())){
            inventory.setInventoryStatus(InventoryEnums.InventoryStatus.COMPLETE.getStatusCode());//完成
            this.update(inventory);
            inventoryReview.setInventoryCode(inventoryCode);
            inventoryReviewService.save(inventoryReview);
            Criteria c = Criteria.create().addCriterion("inventoryCode", Operator.EQ, inventoryCode);
            List<InventoryItem> items = inventoryItemService.list(InventoryItem.class, c);
            Map<String,WarehouseOrder> lossWOrderMap = new HashMap<>();
            Map<String,List<WarehouseOrderLine>> lossWOrderLineMap = new HashMap<>();
            Map<String,WarehouseOrder> plusWOrderMap = new HashMap<>();
            Map<String,List<WarehouseOrderLine>> plusWOrderLineMap = new HashMap<>();
            //生成调差/调盈单
            for (InventoryItem item : items){
                if (StringUtils.equals(item.getHandleMethod(),InventoryEnums.InventoryHandleMethod.LOSS.getStatusCode())){
                    if (!lossWOrderMap.containsKey(item.getWhCode())){
                        //仓单主单
                        WarehouseOrder wo = new WarehouseOrder();
                        wo.setAccessType(OrderEnums.AccessType.OUT.getCode());
                        wo.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
                        wo.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
                        wo.setOrderStatus(OrderStatusEnums.OrderStatus.PLAN.getStatusCode());
                        wo.setOrderDate(new Date());
                        wo.setOriginBizNo(inventoryCode);
                        wo.setWhCode(item.getWhCode());
                        wo.setWoType(NoticeStatusEnums.NoticeType.AO_OUT.getCode());
                        lossWOrderMap.put(item.getWhCode(),wo);
                        //JpaUtil.save(wo);
                    }

                    WarehouseOrderLine line = new WarehouseOrderLine();
                    line.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
                    Item dbItem = JpaUtil.linq(Item.class).idEqual(item.getItemCode()).findOne();
                    line.setItemCode(dbItem.getItemCode());
                    line.setItemGroupCode(dbItem.getItemGroupCode());
                    line.setItemName(dbItem.getItemName());
                    line.setItemSpec(dbItem.getItemSpec());
                    line.setUnitCode(dbItem.getUnitCode());
                    line.setQuantity(item.getInventoryDiffNum().abs());
                    //line.setBizNo(wo.getBizNo());
                    //line.setLineNo(1+"");
                    line.setOriginBizNo(inventoryCode);
                    line.setOriginBizLineNo(item.getLineNo()+"");
                    line.setLotNo(item.getLotNo());
                    line.setSubLotIndex(item.getSubLotIndex());
                    //JpaUtil.save(line);

                    if (!lossWOrderLineMap.containsKey(item.getWhCode())){
                        List<WarehouseOrderLine> lineList = new ArrayList<>();
                        lineList.add(line);
                        lossWOrderLineMap.put(item.getWhCode(),lineList);
                    }else{
                        lossWOrderLineMap.get(item.getWhCode()).add(line);
                    }
                }else if (StringUtils.equals(item.getHandleMethod(),InventoryEnums.InventoryHandleMethod.SURPLUS.getStatusCode())){
                    if (!plusWOrderMap.containsKey(item.getWhCode())){
                        //仓单主单
                        WarehouseOrder wo = new WarehouseOrder();
                        wo.setAccessType(OrderEnums.AccessType.IN.getCode());
                        wo.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
                        wo.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
                        wo.setOrderStatus(OrderStatusEnums.OrderStatus.PLAN.getStatusCode());
                        wo.setOrderDate(new Date());
                        wo.setOriginBizNo(inventoryCode);
                        wo.setWhCode(item.getWhCode());
                        wo.setWoType(NoticeStatusEnums.NoticeType.AO_IN.getCode());
                        //JpaUtil.save(wo);
                        plusWOrderMap.put(item.getWhCode(),wo);
                    }

                    WarehouseOrderLine line = new WarehouseOrderLine();
                    line.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
                    Item dbItem = JpaUtil.linq(Item.class).idEqual(item.getItemCode()).findOne();
                    line.setItemCode(dbItem.getItemCode());
                    line.setItemGroupCode(dbItem.getItemGroupCode());
                    line.setItemName(dbItem.getItemName());
                    line.setItemSpec(dbItem.getItemSpec());
                    line.setUnitCode(dbItem.getUnitCode());
                    line.setQuantity(item.getInventoryDiffNum().abs());
                    //line.setBizNo(wo.getBizNo());
                    //line.setLineNo(1+"");
                    line.setOriginBizNo(inventoryCode);
                    line.setOriginBizLineNo(item.getLineNo()+"");
                    line.setLotNo(item.getLotNo());
                    line.setSubLotIndex(item.getSubLotIndex());
                    //JpaUtil.save(line);
                    if (!plusWOrderLineMap.containsKey(item.getWhCode())){
                        List<WarehouseOrderLine> lineList = new ArrayList<>();
                        lineList.add(line);
                        plusWOrderLineMap.put(item.getWhCode(),lineList);
                    }else{
                        plusWOrderLineMap.get(item.getWhCode()).add(line);
                    }
                }
            }
            if (!lossWOrderMap.isEmpty()){//盘亏保存
                Set<String> whCodes = lossWOrderMap.keySet();
                for (String whCode:whCodes){
                    WarehouseOrder warehouseOrder = lossWOrderMap.get(whCode);
                    JpaUtil.save(warehouseOrder);
                    List<WarehouseOrderLine> warehouseOrderLines = lossWOrderLineMap.get(whCode);
                    for (int i = 0; i < warehouseOrderLines.size(); i++) {
                        WarehouseOrderLine line = warehouseOrderLines.get(i);
                        line.setBizNo(warehouseOrder.getBizNo());
                        line.setWhCode(warehouseOrder.getWhCode());
                        line.setLineNo((i+1)+"");
                        JpaUtil.save(line);
                    }
                }
            }
            if (!plusWOrderMap.isEmpty()){//盘盈保存
                Set<String> whCodes = plusWOrderMap.keySet();
                for (String whCode:whCodes){
                    WarehouseOrder warehouseOrder = plusWOrderMap.get(whCode);
                    JpaUtil.save(warehouseOrder);
                    List<WarehouseOrderLine> warehouseOrderLines = plusWOrderLineMap.get(whCode);
                    for (int i = 0; i < warehouseOrderLines.size(); i++) {
                        WarehouseOrderLine line = warehouseOrderLines.get(i);
                        line.setWhCode(warehouseOrder.getWhCode());
                        line.setBizNo(warehouseOrder.getBizNo());
                        line.setLineNo((i+1)+"");
                        JpaUtil.save(line);
                    }
                }
            }
        }else{//驳回
            inventory.setInventoryStatus(InventoryEnums.InventoryStatus.READY.getStatusCode());//待盘点状态
            this.update(inventory);
            inventoryReview.setInventoryCode(inventoryCode);
            inventoryReviewService.save(inventoryReview);
        }
        return Result.OK();
    }

    @Override
    @Transactional
    public Result<Inventory> saveInventoryItmes(Inventory inventory) {
        List<InventoryItem> itemList = inventory.getItemList();
        String inventoryCode = inventory.getInventoryCode();
        Inventory dbInventory = this.getById(Inventory.class, inventoryCode);
        if (itemList.size()>0){
            for (InventoryItem item:itemList){//仅校验
                BigDecimal inventoryNum = item.getInventoryNum();
                if (inventoryNum==null){
                    return Result.error("提交的盘点任务明细数据中，存在盘点数量为空的情况！");
                }
            }
            for (InventoryItem item:itemList){//由后端来计算盘亏盘盈
                BigDecimal quantity = item.getQuantity();
                BigDecimal inventoryNum = item.getInventoryNum();
                if (inventoryNum.compareTo(quantity)>0){//盘盈
                    item.setHandleMethod(InventoryEnums.HandleMethod.SURPLUS.getCode());
                    item.setInventoryDiffNum(inventoryNum.subtract(quantity).abs());//保证差异数量必须为正数
                }else if (inventoryNum.compareTo(quantity)<0){//盘亏
                    item.setHandleMethod(InventoryEnums.HandleMethod.LACK.getCode());
                    item.setInventoryDiffNum(quantity.subtract(inventoryNum).abs());
                }else{
                    item.setHandleMethod(InventoryEnums.HandleMethod.EQUAL.getCode());
                    item.setInventoryDiffNum(BigDecimal.ZERO);
                }
            }
            inventoryItemService.update(itemList);//
            if (dbInventory.getInventoryActualDate()==null){
                dbInventory.setInventoryActualDate(new Date());//记录实际开始盘点时间
                this.update(dbInventory);
            }
        }else{
            return Result.error("提交的盘点任务明细数据为空");
        }
        return Result.OK();
    }
}
